home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP12.ZIP / PATRON / IDROPTGT.CPP < prev    next >
C/C++ Source or Header  |  1993-07-19  |  15KB  |  587 lines

  1. /*
  2.  * IDROPTGT.CPP
  3.  *
  4.  * Implementation of a DropTarget object for Patron, modified for
  5.  * Chapter 12 to handle link feedback.
  6.  *
  7.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  8.  *
  9.  * Kraig Brockschmidt, Software Design Engineer
  10.  * Microsoft Systems Developer Relations
  11.  *
  12.  * Internet  :  kraigb@microsoft.com
  13.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  14.  */
  15.  
  16.  
  17. #include "patron.h"
  18.  
  19.  
  20.  
  21. /*
  22.  * CDropTarget::CDropTarget
  23.  * CDropTarget::~CDropTarget
  24.  *
  25.  * Constructor Parameters:
  26.  *  pDoc            LPCPatronDoc of the window containing us.
  27.  */
  28.  
  29. CDropTarget::CDropTarget(LPCPatronDoc pDoc)
  30.     {
  31.     m_cRef=0;
  32.     m_pDoc=pDoc;
  33.  
  34.     m_pIDataObject=NULL;
  35.     return;
  36.     }
  37.  
  38.  
  39. CDropTarget::~CDropTarget(void)
  40.     {
  41.     return;
  42.     }
  43.  
  44.  
  45.  
  46.  
  47. /*
  48.  * CDropTarget::QueryInterface
  49.  * CDropTarget::AddRef
  50.  * CDropTarget::Release
  51.  *
  52.  * Purpose:
  53.  *  IUnknown members for CDropTarget object.
  54.  */
  55.  
  56. STDMETHODIMP CDropTarget::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  57.     {
  58.     *ppv=NULL;
  59.  
  60.     //Any interface on this object is the object pointer.
  61.     if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDropTarget))
  62.         *ppv=(LPVOID)this;
  63.  
  64.     /*
  65.      * If we actually assign an interface to ppv we need to AddRef it
  66.      * since we're returning a new pointer.
  67.      */
  68.     if (NULL!=*ppv)
  69.         {
  70.         ((LPUNKNOWN)*ppv)->AddRef();
  71.         return NOERROR;
  72.         }
  73.  
  74.     return ResultFromScode(E_NOINTERFACE);
  75.     }
  76.  
  77.  
  78. STDMETHODIMP_(ULONG) CDropTarget::AddRef(void)
  79.     {
  80.     return ++m_cRef;
  81.     }
  82.  
  83. STDMETHODIMP_(ULONG) CDropTarget::Release(void)
  84.     {
  85.     ULONG           cRefT;
  86.  
  87.     cRefT=--m_cRef;
  88.  
  89.     if (0L==m_cRef)
  90.         delete this;
  91.  
  92.     return cRefT;
  93.     }
  94.  
  95.  
  96.  
  97.  
  98.  
  99. /*
  100.  * CDropTarget::DragEnter
  101.  *
  102.  * Purpose:
  103.  *  Indicates that data in a drag operation has been dragged over our
  104.  *  window that's a potential target.  We are to decide if it's something
  105.  *  we're interested in or not.
  106.  *
  107.  * Parameters:
  108.  *  pIDataSource    LPDATAOBJECT providing the source data.
  109.  *  grfKeyState     DWORD flags indicating states of keys and mouse buttons.
  110.  *  pt              POINTL coordinates in the client space of the document.
  111.  *  pdwEffect       LPDWORD into which we'll place the appropriate effect
  112.  *                  flag for this point.
  113.  *
  114.  * Return Value:
  115.  *  SCODE           NOERROR
  116.  */
  117.  
  118. STDMETHODIMP CDropTarget::DragEnter(LPDATAOBJECT pIDataSource
  119.     , DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
  120.     {
  121.     LPCPages        ppg=m_pDoc->m_pPG;
  122.     HWND            hWnd;
  123.     FORMATETC       fe;
  124.     STGMEDIUM       stm;
  125.     UINT            uRet;
  126.  
  127.     m_fFeedback=FALSE;
  128.     m_pIDataObject=NULL;
  129.  
  130.     if (!m_pDoc->FQueryPasteFromData(pIDataSource, &fe, NULL))
  131.         {
  132.         *pdwEffect=DROPEFFECT_NONE;
  133.         return NOERROR;
  134.         }
  135.  
  136.     //CHAPTER12MOD
  137.     //Check if we can link from this data object as well.
  138.     ppg->m_fLinkAllowed=SUCCEEDED(OleQueryLinkFromData(pIDataSource));
  139.  
  140.     //We never allow it dragging in ourselves.
  141.     ppg->m_fLinkAllowed &= !ppg->m_fDragSource;
  142.     //End CHAPTER12MOD
  143.  
  144.     //Check if this is a valid drop point.
  145.     uRet=ppg->UTestDroppablePoint(&pt);
  146.     ppg->m_uLastTest=uRet;
  147.  
  148.     if (UDROP_NONE==uRet)
  149.         *pdwEffect=DROPEFFECT_NONE;
  150.     else
  151.         {
  152.         //Default is move if we can, in fact drop here.
  153.         *pdwEffect=DROPEFFECT_MOVE;
  154.  
  155.         //CHAPTER12MOD
  156.         if (grfKeyState & MK_CONTROL)
  157.             {
  158.             if (ppg->m_fLinkAllowed && (grfKeyState & MK_SHIFT))
  159.                 *pdwEffect=DROPEFFECT_LINK;
  160.             else
  161.                 *pdwEffect=DROPEFFECT_COPY;
  162.             }
  163.         //End CHAPTER12MOD
  164.         }
  165.  
  166.     m_pIDataObject=pIDataSource;
  167.     m_pIDataObject->AddRef();
  168.  
  169.     /*
  170.      * Determine the size of the data, if we can.  The default is
  171.      * a small rectangle since we can't easily tell what size something
  172.      * will be if we're pulling in a metafile or bitmap.  It's not
  173.      * a good idea to render it here with ::GetData just to find that out.
  174.      * We only know the size if it's our own object in which case a
  175.      * ::GetData will be fast.
  176.      */
  177.  
  178.     if (fe.cfFormat==m_pDoc->m_cf)
  179.         {
  180.         if (SUCCEEDED(pIDataSource->GetData(&fe, &stm)))
  181.             {
  182.             LPPATRONOBJECT  ppo;
  183.             RECT            rc;
  184.  
  185.             ppo=(LPPATRONOBJECT)GlobalLock(stm.hGlobal);
  186.  
  187.             SetRect(&rc, (int)ppo->szl.cx, -(int)ppo->szl.cy, 0, 0);
  188.             RectConvertMappings(&rc, NULL, TRUE);
  189.             SETSIZEL(m_szl, rc.left, rc.top);
  190.  
  191.             m_ptPick=ppo->ptlPick;
  192.             m_fe=ppo->fe;
  193.  
  194.             GlobalUnlock(stm.hGlobal);
  195.             ReleaseStgMedium(&stm);
  196.             }
  197.         }
  198.     else
  199.         {
  200.         SETSIZEL(m_szl, 30, 30);
  201.         m_ptPick.x=0;
  202.         m_ptPick.y=0;
  203.         m_fe.cfFormat=0;
  204.  
  205.         /*
  206.          * Try to get CF_OBJECTDESCRIPTOR which might have a size and
  207.          * a pick point.  If it exists, then always use the point but
  208.          * still default to a 30*30 size if the sizes are zero.
  209.          */
  210.         uRet=RegisterClipboardFormat(CF_OBJECTDESCRIPTOR);
  211.         SETDefFormatEtc(fe, uRet, TYMED_HGLOBAL);
  212.  
  213.         if (SUCCEEDED(pIDataSource->GetData(&fe, &stm)))
  214.             {
  215.             LPOBJECTDESCRIPTOR  pOD;
  216.  
  217.             pOD=(LPOBJECTDESCRIPTOR)GlobalLock(stm.hGlobal);
  218.  
  219.             //Get the size, converting to LOMETRIC.
  220.             if (0!=pOD->sizel.cx && 0!=pOD->sizel.cy)
  221.                 XformSizeInHimetricToPixels(NULL, &pOD->sizel, &m_szl);
  222.  
  223.             //POINTL and SIZEL are interchangeable
  224.             XformSizeInHimetricToPixels(NULL, (LPSIZEL)&pOD->pointl
  225.                 , (LPSIZEL)&m_ptPick);
  226.  
  227.             GlobalUnlock(stm.hGlobal);
  228.             ReleaseStgMedium(&stm);
  229.             }
  230.         }
  231.  
  232.  
  233.     //Bring the document window up front and show what a drop will do.
  234.     hWnd=m_pDoc->Window();
  235.     BringWindowToTop(hWnd);
  236.     UpdateWindow(hWnd);
  237.  
  238.     ppg->m_uVScrollCode=0xFFFF;
  239.     ppg->m_uHScrollCode=0xFFFF;
  240.     m_fPendingRepaint=FALSE;
  241.  
  242.     pt.x-=m_ptPick.x;
  243.     pt.y-=m_ptPick.y;
  244.  
  245.     m_ptLast=pt;
  246.     m_fFeedback=TRUE;
  247.     ppg->DrawDropTargetRect(&pt, &m_szl);
  248.  
  249.     return NOERROR;
  250.     }
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257. /*
  258.  * CDropTarget::DragOver
  259.  *
  260.  * Purpose:
  261.  *  Indicates that the mouse was moved inside the window represented
  262.  *  by this drop target.  This happens on every WM_MOUSEMOVE, so this
  263.  *  function should be very efficient.
  264.  *
  265.  * Parameters:
  266.  *  grfKeyState     DWORD providing the current keyboard and mouse states
  267.  *  pt              POINTL where the mouse currently is.
  268.  *  pdwEffect       LPDWORD in which to store the effect flag for this point.
  269.  *
  270.  * Return Value:
  271.  *  SCODE           NOERROR
  272.  */
  273.  
  274. STDMETHODIMP CDropTarget::DragOver(DWORD grfKeyState, POINTL pt
  275.     , LPDWORD pdwEffect)
  276.     {
  277.     LPCPages    ppg=m_pDoc->m_pPG;
  278.     UINT        uRet, uLast;
  279.     UINT        xPos, yPos;
  280.  
  281.     *pdwEffect=DROPEFFECT_NONE;
  282.  
  283.     if (NULL==m_pIDataObject)
  284.         return NOERROR;
  285.  
  286.     //Check if this is still a valid point.  uRet is used below as well.
  287.     uRet=ppg->UTestDroppablePoint(&pt);
  288.  
  289.     if (UDROP_NONE==uRet)
  290.         *pdwEffect=DROPEFFECT_NONE;
  291.     else
  292.         {
  293.         //Store these before possibly ORing in DROPEFFECT_SCROLL
  294.         *pdwEffect=DROPEFFECT_MOVE;
  295.  
  296.         //CHAPTER12MOD
  297.         if (grfKeyState & MK_CONTROL)
  298.             {
  299.             if (ppg->m_fLinkAllowed && (grfKeyState & MK_SHIFT))
  300.                 *pdwEffect=DROPEFFECT_LINK;
  301.             else
  302.                 *pdwEffect=DROPEFFECT_COPY;
  303.             }
  304.         //End CHAPTER12MOD
  305.         }
  306.  
  307.     //If we haven't moved and we are not scrolling, then we're done.
  308.     if ((pt.x-m_ptPick.x==m_ptLast.x) && (pt.y-m_ptPick.y==m_ptLast.y)
  309.         && !((UDROP_INSETHORZ | UDROP_INSETVERT) & ppg->m_uLastTest))
  310.         {
  311.         return NOERROR;
  312.         }
  313.  
  314.     //Remove the last feedback rectangle.
  315.     if (m_fFeedback)
  316.         ppg->DrawDropTargetRect(&m_ptLast, &m_szl);
  317.  
  318.     uLast=ppg->m_uLastT